package com.xdh.springcloud.security.jwt;

import com.xdh.springcloud.security.jwt.auth.ajax.AjaxAuthenticationFailureHandler;
import com.xdh.springcloud.security.jwt.auth.ajax.AjaxAuthenticationProvider;
import com.xdh.springcloud.security.jwt.auth.ajax.AjaxLoginProcessingFilter;
import com.xdh.springcloud.security.jwt.auth.jwt.JwtAuthenticationFailureHandler;
import com.xdh.springcloud.security.jwt.auth.jwt.JwtAuthenticationProvider;
import com.xdh.springcloud.security.jwt.common.CustomCorsFilter;
import com.xdh.springcloud.security.jwt.common.config.AuthConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.util.Arrays;
import java.util.List;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends AbstractWebSecurityConfig {
    @Autowired
    private AuthenticationSuccessHandler successHandler;

    @Autowired
    private AjaxAuthenticationFailureHandler ajaxAuthenticationFailureHandler;

    @Autowired
    private AjaxAuthenticationProvider ajaxAuthenticationProvider;

    @Autowired
    private JwtAuthenticationProvider jwtAuthenticationProvider;

    @Autowired
    private AuthenticationManager authenticationManager;


    protected AjaxLoginProcessingFilter buildAjaxLoginProcessingFilter(String loginEntryPoint) {
        AjaxLoginProcessingFilter filter = new AjaxLoginProcessingFilter(loginEntryPoint, successHandler, ajaxAuthenticationFailureHandler);
        filter.setAuthenticationManager(this.authenticationManager);
        return filter;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(ajaxAuthenticationProvider);
        auth.authenticationProvider(jwtAuthenticationProvider);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        List<String> permitAllEndpointList = Arrays.asList(
                AuthConfig.AUTHENTICATION_URL
        );

        http
                .csrf().disable() // We don't need CSRF for JWT based authentication
//                .authenticationEntryPoint(this.authenticationEntryPoint)
//                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)

                .and()
                .authorizeRequests()
                .antMatchers(AuthConfig.AUTHENTICATION_URL)
                .permitAll()

                .and()
                .authorizeRequests()
                .antMatchers(AuthConfig.API_ROOT_URL).authenticated() // Protected API End-points

                .and()
                .addFilterBefore(new CustomCorsFilter(), UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(buildAjaxLoginProcessingFilter(AuthConfig.AUTHENTICATION_URL), UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(buildJwtTokenAuthenticationProcessingFilter(permitAllEndpointList, AuthConfig.API_ROOT_URL), UsernamePasswordAuthenticationFilter.class);
    }

}
